<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>气泡魔法世界</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet" />
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: "#3B82F6",
            secondary: "#8B5CF6",
            success: "#10B981",
            warning: "#F59E0B",
            error: "#EF4444",
            bubble1: "#1D4ED8", // 鲜亮深蓝
            bubble2: "#7C3AED", // 鲜紫
            bubble3: "#F43F5E", // 鲜红粉
            bubble4: "#06D6A0", // 鲜绿
            bubble5: "#FFB800", // 鲜橙黄
          },
          fontFamily: {
            fantasy: ['"Comic Sans MS"', '"Marker Felt"', "sans-serif"],
          },
          backgroundImage: {
            "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
          },
        },
      },
    };
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>

  <style type="text/tailwindcss">
    @layer utilities {
        .content-auto {
          content-visibility: auto;
        }
        .bubble {
          position: absolute;
          border-radius: 50%;
          box-shadow: 0 0 10px rgba(255, 255, 255, 0.7) inset;
          animation: float 3s ease-in-out infinite;
        }
        @keyframes float {
          0%,
          100% {
            transform: translateY(0);
          }
          50% {
            transform: translateY(-10px);
          }
        }
        .bubble-pop {
          animation: pop 0.5s ease-out forwards;
        }
        @keyframes pop {
          0% {
            transform: scale(0);
            opacity: 0;
          }
          50% {
            transform: scale(1.2);
            opacity: 0.8;
          }
          100% {
            transform: scale(1);
            opacity: 1;
          }
        }
        .bubble-container {
          perspective: 1000px;
          overflow: hidden;
        }
        .choice-box {
          transition: all 0.3s ease;
          background-image: radial-gradient(
            circle at center,
            rgba(255, 255, 255, 0.1),
            rgba(255, 255, 255, 0)
          );
        }
        .choice-box:hover {
          transform: translateY(-5px);
          box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
        }
        .feedback-animation {
          animation: pulse 0.6s ease-in-out;
        }
        @keyframes pulse {
          0%,
          100% {
            transform: scale(1);
          }
          50% {
            transform: scale(1.05);
          }
        }
        .progress-bar {
          transition: width 0.1s linear;
        }
        .timer-warning {
          animation: blink 1s infinite;
        }
        @keyframes blink {
          0%,
          100% {
            opacity: 1;
          }
          50% {
            opacity: 0.5;
          }
        }
        .cloud {
          position: absolute;
          opacity: 0.5;
          animation: cloud-move 30s linear infinite;
        }
        @keyframes cloud-move {
          0% {
            transform: translateX(-100%);
          }
          100% {
            transform: translateX(100%);
          }
        }
        .disabled-button {
          background: gray;
          cursor: not-allowed;
        }
      }
    </style>

  <style>
    #gender {
      background-image: url('data:image/svg+xml;charset=US-ASCII,<svg width=" 20"height="20" xmlns="http://www.w3.org/2000/svg"><path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 001-1.414 0l-4-4a1 1 0 010-1.414z" fill="%23ffffff" /></svg>');
    }

    .form-group input::placeholder {
      color: #c8c8c8;
    }

    .slider-container {
      position: relative;
      width: 250px;
    }

    .value-label {
      position: absolute;
      top: 40px;
      font-size: 14px;
      color: #fff;
      white-space: nowrap;
      pointer-events: none;
    }

    input[type="range"] {
      -webkit-appearance: none;
      width: 100%;
      height: 4px;
      background: #fff;
      border-radius: 2px;
      outline: none;
    }

    input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 0;
      height: 0;
      border-left: 6px solid transparent;
      border-right: 6px solid transparent;
      border-bottom: 15px solid #fff;
      margin-top: 30px;
      cursor: pointer;
    }

    .rect-container {
      width: 100px;
      height: 100px;
      margin: 0 auto;
      border: 1px solid black;
      position: relative;
      border-radius: 50%;
      overflow: hidden;
      background-color: #fff;
    }

    .rect {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 10px;
      height: 10px;
      background-color: #ed7d31;
      border-radius: 50%;
      transform: translate(-50%, -50%) scale(0);
      transition: transform 1s ease;
      /* 动画时间1秒 */

    }
  </style>
</head>

<body class="bg-gradient-to-br from-primary/90 to-secondary/90 font-fantasy min-h-screen flex flex-col">
  <!-- 背景装饰 -->
  <!-- <div class="fixed inset-0 pointer-events-none z-0">
    <div class="cloud w-40 h-20 top-10 left-0" style="animation-delay: 0s">
      <div class="w-full h-full rounded-full bg-white"></div>
    </div>
    <div class="cloud w-60 h-30 top-20 left-1/4" style="animation-delay: 10s">
      <div class="w-full h-full rounded-full bg-white"></div>
    </div>
    <div class="cloud w-50 h-25 bottom-20 right-1/3" style="animation-delay: 5s">
      <div class="w-full h-full rounded-full bg-white"></div>
    </div>
    <div class="cloud w-30 h-15 bottom-40 right-1/4" style="animation-delay: 15s">
      <div class="w-full h-full rounded-full bg-white"></div>
    </div>
  </div> -->

  <!-- 头部区域 -->
  <header class="text-white shadow-lg relative z-10">
    <div class="container mx-auto px-4 py-6">
      <h1 class="text-[clamp(1.8rem,4vw,3rem)] font-bold text-center tracking-tight drop-shadow-lg">
        <i class="fa-solid fa-magic-wand-sparkles mr-2"></i>气泡魔法世界
      </h1>
      <p class="text-center mt-2 opacity-90">
        <span class="font-bold">找出气泡更多的一边，</span>成为气泡魔法师！
      </p>
    </div>
  </header>

  <!-- 主要内容区域 -->
  <main class="flex-grow container mx-auto px-4 py-8 relative z-10">
    <!-- 游戏介绍 -->
    <!-- 0. 介绍 -->
    <div id="step0" class="w-2/3 m-auto mt-24 hidden transition-opacity text-center">
      <div class="w-full text-white font-bold text-2xl tips">
        接下来两侧的点数会增加，释放魔法的规则不变。
      </div>
      <div class="w-full mt-4 mb-8 text-white font-bold text-2xl tips">
        请在保证正确的情况下，用最快的速度反应。
      </div>
      <button disabled onclick="startExperiment(0)"
        class="start-btn m-auto block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
        开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
      </button>
    </div>
    <!-- 第一关.介绍 -->

    <div id="step_tips" class="w-2/3 m-auto hidden  transition-opacity text-white mt-20">
      <div class="flex m-auto w-10/12 items-center justify-center my-3 mt16 gap-x-16">
        <div class="text-center">
          <div class="my-1 level-title">休息</div>
          <img src="./img/effort.png" alt="" srcset="" class="w-28 img level-img m-auto block" />
        </div>
        <div class="text-center hidden easy">
          <div class="my-1 easy-title">容易成功</div>
          <img src="./img/easy.png" alt="" srcset="" class="h-40 img easy-img m-auto block" />
        </div>
      </div>
    </div>
    <!--  -->
    <div id="step_2_tips" class="w-2/3 m-auto hidden transition-opacity text-white mt-20">
      <div class="flex m-auto w-10/12 items-center justify-center my-3 mt16 gap-x-16">
        <div onclick="selectFun(1)"
          class="cursor-pointer	hover:-translate-y-6 duration-300 bg-[#7092f8] w-3/6 py-8 rounded-3xl flex items-center justify-center">
          <div class="text-center">
            <div class="my-1 level-title">休息</div>
            <img src="./img/effort.png" alt="" srcset="" class="w-28 img level-img m-auto block" />
          </div>
          <div class="text-center easy">
            <div class="my-1 easy-title">容易成功</div>
            <img src="./img/easy.png" alt="" srcset="" class="h-40 img easy-img m-auto block" />
          </div>
        </div>
        <div
          class="cursor-pointer text-center hover:-translate-y-6 step_3 step_4 duration-300 w-3/6 bg-[#7092f8] py-8 rounded-3xl "
          onclick="selectFun(0)">
          <div class="my-1">休息</div>
          <img src="./img/effort.png" alt="" srcset="" class="w-28 img m-auto block" />
        </div>
      </div>
    </div>

    <div id="step1" class="w-2/3 m-auto hidden transition-opacity text-white">
      <div class="text-center mt-5 w-full mb-8 font-bold text-4xl">
        第一节课,体验不同努力水平的魔法
      </div>
      <div class="mt-5 w-full mb-8 text-xl">
        <div>
          接下来你会完成不同气泡数量的魔法，气泡越多，你需要付出的努力越多。
        </div>
        <div class="my-1">
          代表努力水平的图标如下，图标中紫蓝色部分越多代表需要的努力越多。
        </div>
        <div>
          如果图标中没有紫蓝色部分，代表这是一个休息任务，在休息任务中，你只需要看着屏幕就可以了（3秒钟）。
        </div>
        <div class="my-1">
          一共有5种努力水平。请在保证正确的情况下，尽可能快地做出反应！
        </div>
      </div>
      <div class="flex m-auto w-10/12 items-center justify-between my-3">
        <div class="flex text-center gap-x-3">
          <div>
            <div class="my-1">休息</div>
            <img src="./img/effort.png" alt="" srcset="" class="w-24" />
          </div>
          <div>
            <div class="my-1">努力水平1</div>
            <img src="./img/effort1.png" alt="" srcset="" class="w-24" />
          </div>
          <div>
            <div class="my-1">努力水平2</div>
            <img src="./img/effort2.png" alt="" srcset="" class="w-24" />
          </div>
          <div>
            <div class="my-1">努力水平3</div>
            <img src="./img/effort3.png" alt="" srcset="" class="w-24" />
          </div>
          <div>
            <div class="my-1">努力水平4</div>
            <img src="./img/effort4.png" alt="" srcset="" class="w-24" />
          </div>
        </div>
        <button disabled onclick="startExperiment(1)"
          class="start-btn block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
          开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
        </button>
      </div>
    </div>

    <div id="step2" class="w-2/3 m-auto hidden transition-opacity text-white">
      <div class="text-center mt-5 w-full font-bold text-4xl">
        第二节课,体验不同释放速度的气泡魔法
      </div>
      <div class="w-full text-xl mt-5">
        接下来，会教你以两种速度释放不同努力水平的气泡魔法。一种速度较慢，留给你的反应时间长，容易成功；
      </div>
      <div class="w-full text-xl mt-1">
        另一种速度较快，留给你反应时间短，不容易成功。
      </div>
      <div class="w-full text-xl mt-1">
        代表释放速度的沙漏图标如下，沙漏中的绿色沙子越多，代表留给你的反应时间长，越容易成功。
      </div>
      <div class="w-full mb-8 text-xl mt-1">
        如果准备好了请点击开始冒险按钮。
      </div>

      <div class="flex m-auto w-9/12 items-center justify-between my-3">
        <div class="flex text-center gap-x-16">
          <div>
            <div class="my-1">容易成功</div>
            <img src="./img/easy.png" alt="" srcset="" class="w-24" />
          </div>
          <div class="ml-4">
            <div class="my-1">不容易成功</div>
            <img src="./img/not-easy.png" alt="" srcset="" class="w-24" />
          </div>
        </div>
        <button disabled onclick="startExperiment(2)"
          class="start-btn block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
          开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
        </button>
      </div>
    </div>

    <div id="step3" class="w-2/3 m-auto hidden text-white transition-opacity">
      <div class="text-center mt-5 w-full mb-8 font-bold text-4xl">
        第三节课,静态魔法预演
      </div>
      <div class="mt-5 w-full mb-8 text-xl">
        <div>
          接下来，我们想了解你想要释放哪些气泡魔法，屏幕中会出现代表当前魔法的努力水平和多容易成功的图标，你可以自由选择释放魔法或者选择休息。
        </div>
        <div class="mt-1">
          在这节课中，我们只是想了解你想要释放哪些气泡魔法，所以当你选择释放魔法后并不会真的让你做这个任务。
        </div>
        <div class="mt-1">
          如果你想要选择释放魔法就点击“释放魔法”按钮，如果你想要选择休息就点击“休息”按钮。
        </div>
      </div>
      <button disabled onclick="startExperiment(3)"
        class="start-btn m-auto block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
        开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
      </button>
    </div>
    <div id="step4" class="w-2/3 m-auto hidden text-white transition-opacity">
      <div class="text-center mt-5 w-full mb-8 font-bold text-4xl">
        正式魔法冒险
      </div>
      <div class="mt-5 w-full mb-8 text-xl">
        <div>
          接下来，屏幕中会出现代表当前魔法的努力水平和多容易成功的图标，你可以自由选择释放魔法或者选择休息。
        </div>
        <div class="mt-1">
          我们还想了解你现在的开心和疲劳程度。请用滑条对你现在的开心程度打分。
        </div>
        <div class="mt-1">请用滑条对你现在的疲劳程度打分。</div>
        <div class="mt-1">接下来每个任务结束后，都会请你对自己开心和疲劳的程度打分（0-100分）。</div>
        <div class="mt-1">如果评好分并且准备好了就点击“开始冒险”按钮。</div>
      </div>


      <div class="flex w-full justify-between m-auto mb-8">
        <div class="text-center border-2 border-white p-4 h-28 select-none">
          <div>开心程度</div>
          <div class="flex items-center">
            <div>非常不开心</div>
            <div class="slider-container mx-4">
              <input type="range" min="0" max="100" value="50" class="slider " title="开心程度" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
            <div>非常开心</div>
          </div>
        </div>
        <div class="text-center border-2 border-white p-4 h-28 select-none">
          <div>疲劳程度</div>
          <div class="flex items-center">
            <div>非常不疲劳</div>
            <div class="slider-container mx-4">
              <input type="range" min="0" max="100" value="50" class="slider " title="疲劳程度" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
            <div>非常疲劳</div>
          </div>
        </div>

      </div>
      <button disabled onclick="startExperiment(4)"
        class="start-btn m-auto block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
        开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
      </button>
    </div>
    <div id="score1" class="w-2/3 m-auto hidden text-white transition-opacity">
      <div class="mt-5 w-full mb-8 text-xl">
        <div>
          回忆一下刚才释放魔法的感受，请用滑条对每个努力大小的任务打分。
        </div>
        <div class="my-1">
          滑条长度和对应的分数代表你实际付出努力的大小，滑条越长数值越大，代表你实际付出了更多努力。
        </div>
        <div>0分代表没有付出努力，100分代表付出了全部努力。</div>
        <div class="my-1">
          如果你评好分了，请按提交键提交结果，进入下一节课。
        </div>
      </div>
      <div class="flex w-10/12 justify-between m-auto">
        <div>
          <div class="flex items-center my-9 select-none">
            <img src="./img/effort.png" alt="" srcset="" class="w-7" />
            <div class="text-center w-24">休息</div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="休息" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
          <div class="flex items-center my-9 select-none">
            <img src="./img/effort1.png" alt="" srcset="" class="w-7" />
            <div class="text-center w-24">努力水平1</div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="努力水平1" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
          <div class="flex items-center my-9 select-none">
            <img src="./img/effort2.png" alt="" srcset="" class="w-7" />
            <div class="text-center w-24">努力水平2</div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="努力水平2" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
          <div class="flex items-center my-9 select-none">
            <img src="./img/effort3.png" alt="" srcset="" class="w-7" />
            <div class="text-center w-24">努力水平3</div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="努力水平3" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
        </div>
        <div>
          <div class="flex items-center my-9 select-none">
            <img src="./img/effort4.png" alt="" srcset="" class="w-7" />
            <div class="text-center w-24">努力水平4</div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="努力水平4" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
          <button onclick="submitScore(1)"
            class="mt-48 start-btn block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
            提交结果 <i class="fa-solid fa-arrow-right ml-2"></i>
          </button>
        </div>
      </div>
    </div>
    <div id="score2" class="w-2/3 m-auto hidden text-white transition-opacity">
      <div class="mt-5 w-full mb-8 text-xl">
        <div>
          回忆一下刚才释放魔法的感受，请用滑条对两种释放速度的任务打分。
        </div>
        <div class="my-1">
          滑条长度和对应分数代表你感受到这个任务有多容易成功，滑条越长数值越大，代表越容易成功。
        </div>
        <div>0分代表无法成功，100分代表肯定能成功。</div>
        <div class="my-1">
          如果你评好分了，请按提交键提交结果，进入下一节课。
        </div>
      </div>
      <div class="flex w-10/12 justify-between m-auto items-center">
        <div>
          <div class="flex items-center my-12 select-none">
            <div class="text-center mr-12">
              <div class="">容易成功</div>
              <img src="./img/easy.png" alt="" srcset="" class="w-16" />
            </div>
            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="容易成功" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
          <div class="flex items-center my-12 select-none">
            <div class="text-center mr-9">
              <div>不容易成功</div>
              <img src="./img/not-easy.png" alt="" srcset="" class="w-16" />
            </div>

            <div class="slider-container">
              <input type="range" min="0" max="100" value="50" class="slider" title="不容易成功" />
              <div class="value-label" id="valueLabel">50</div>
            </div>
          </div>
        </div>
        <button onclick="submitScore(2)"
          class="start-btn block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
          提交结果 <i class="fa-solid fa-arrow-right ml-2"></i>
        </button>
      </div>
    </div>
    <!-- 实验评分 -->
    <div id="experiment-score" class="w-1/2 m-auto hidden text-white transition-opacity">
      <div class="text-center border-2 border-white p-4 h-28 select-none">
        <div>开心程度</div>
        <div class="flex items-center">
          <div>非常不开心</div>
          <div class="slider-container mx-4 w-9/12">
            <input type="range" min="0" max="100" value="50" class="slider" title="开心程度" />
            <div class="value-label" id="valueLabel">50</div>
          </div>
          <div>非常开心</div>
        </div>
      </div>
      <div class="text-center border-2 border-white mt-16 p-4 h-28 select-none">
        <div>疲劳程度</div>
        <div class="flex items-center">
          <div>非常不疲劳</div>
          <div class="slider-container mx-4 w-9/12">
            <input type="range" min="0" max="100" value="50" class="slider " title="疲劳程度" />
            <div class="value-label" id="valueLabel">50</div>
          </div>
          <div>非常疲劳</div>
        </div>
      </div>
      <button onclick="step4Score()"
        class="start-btn block m-auto bg-gradient-to-r mt-4 from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
        提交结果
      </button>
    </div>
    <!-- 暂停 -->
    <div id="game-pause" class="hidden transition-opacity">
      <div class="text-center mt-32 w-full mb-8 text-white font-bold text-2xl">
        魔法学徒，请休息一下吧！
      </div>
      <button id="game-continue" disabled onclick="gameContinueFun()"
        class="m-auto block bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
        继续冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
      </button>
    </div>
    <!-- 选择 的提示 -->
    <div id="select-pause"
      class="hidden transition-opacity text-center mt-32 w-full mb-8 text-white font-bold text-2xl">
      魔法学徒，请休息一下吧！
    </div>
    <!-- 欢迎页面 -->
    <div id="simple-welcome"
      class="transition-opacity max-w-3xl mx-auto bg-white/20 backdrop-blur-lg rounded-2xl shadow-xl p-8 transform transition-all duration-500 border border-white/30 hidden">
      <div class="text-center mb-8">
        <div class="relative inline-block">
          <i class="fa-solid fa-cloud text-white text-7xl mb-4"></i>
          <i
            class="fa-solid fa-magic-wand-sparkles text-primary text-5xl absolute top-6 left-1/2 transform -translate-x-1/2 animate-pulse"></i>
        </div>
        <h2 class="text-[clamp(1.5rem,3vw,2rem)] font-bold text-white mb-3">
          欢迎来到气泡魔法世界
        </h2>
        <p class="text-white/80 text-2xl font-bold leading-relaxed">
          这是一个充满魔法的气泡世界！你的任务是用鼠标点击气泡更多的一边，释放魔法。
        </p>
      </div>

      <div class="bg-white/10 rounded-xl p-6 mb-8 border border-white/20">
        <h3 class="font-semibold text-lg text-white mb-3 flex items-center">
          <i class="fa-solid fa-book mr-2 text-white"></i>游戏说明
        </h3>
        <ul class="space-y-3 text-white/90 text-lg">

          <li class="flex items-start">
            <span>1、每次在释放魔法前，需要你将鼠标放在指定圈内积攒魔力。</span>
          </li>
          <li class="flex items-start">
            <span>2、如果你在指定时间内答对，气泡外框会变成绿色，随后呈现对勾。</span>
          </li>
          <li class="flex items-start">
            <span>3、如果你答错，气泡外框会变成红色，随后呈现叉。</span>
          </li>
          <li class="flex items-start">
            <span>4、如果你答对，但超时了，气泡外框会变成黄色，随后呈现叉。</span>
          </li>
          <li class="flex items-start">
            <span>5、接下来会让你练习最简单的气泡魔法。如果准备好了请点击下方按钮开始冒险！</span>
          </li>
          <!--                    <li class="flex items-start">-->
          <!--                        <i class="fa-solid fa-times-circle text-error mt-1 mr-2"></i>-->
          <!--                        <span>答错：气泡会变成暗淡的红色</span>-->
          <!--                    </li>-->
          <!--                    <li class="flex items-start">-->
          <!--                        <i class="fa-solid fa-trophy text-yellow-400 mt-1 mr-2"></i>-->
          <!--                        <span>完成10个关卡后，你将获得魔法评分！</span>-->
          <!--                    </li>-->
        </ul>
      </div>
      <div class="text-center">
        <button id="start" onclick="startSimpleExperiment()"
          class="bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30"
          disabled>
          开始冒险 <i class="fa-solid fa-arrow-right ml-2"></i>
        </button>
      </div>
    </div>

    <div id="start-before" class="hidden transition-opacity">
      <div class="text-center mt-24 w-full mb-8 text-white font-bold text-2xl">
        请将鼠标移动圆内积攒魔力
      </div>
      <div class="rect-container mt-12">
        <div class="rect"></div>
      </div>
    </div>

    <!-- 简单练习 -->
    <div id="simple-experiment" class="max-w-5xl mx-auto hidden transition-opacity">
      <!-- 进度条 -->
      <div
        class="bg-white/20 backdrop-blur-md rounded-xl shadow-md p-4 mb-6 border border-white/30 hidden transition-opacity">
        <div class="flex justify-between items-center my-2.5">
          <span class="text-white font-medium">
            <i class="fa-solid fa-tasks mr-1"></i> 关卡进度:
            <span id="trial-count">1</span>/10
          </span>
          <span class="text-white font-medium">
            <i class="fa-solid fa-clock mr-1"></i> 剩余时间:
            <span id="timerEl" class="font-bold text-warning">3</span>秒
          </span>
        </div>
        <div class="w-full bg-white/10 rounded-full h-2.5">
          <div id="simple-progress" class="progress-bar bg-gradient-to-r from-primary to-secondary h-2.5 rounded-full"
            style="width: 10%"></div>
        </div>
      </div>
      <!-- 气泡容器 -->
      <div
        class="bubble-container bg-white/10 backdrop-blur-md rounded-2xl shadow-xl p-6 md:p-10 min-h-[400px] flex items-center justify-center border border-white/30">
        <div class="w-full flex flex-col md:flex-row gap-6">
          <!-- 左侧气泡 -->
          <div id="simple-left" onclick="simpleClick('left')"
            class="choice-box flex-1 relative aspect-square rounded-xl border-4 border-transparent cursor-pointer overflow-hidden"
            data-choice="left">
            <div class="absolute inset-0 bg-gradient-to-br from-blue-500/20 to-purple-500/20 rounded-lg"></div>
            <div id="simple-leftdots" class="absolute inset-0 p-4"></div>
            <div
              class="absolute inset-0 flex items-center justify-center bg-black/10 hover:bg-black/20 transition-colors rounded-lg">
              <!-- <span class="text-white text-2xl font-bold opacity-0 hover:opacity-100 transition-opacity">点击选择</span> -->
            </div>
            <!--                        <div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 text-white font-bold text-lg">左边</div>-->
          </div>

          <!-- 中间分隔 -->
          <div class="hidden md:block w-px bg-white/20"></div>

          <!-- 右侧气泡 -->
          <div id="simple-right" onclick="simpleClick('right')"
            class="choice-box flex-1 relative aspect-square rounded-xl border-4 border-transparent cursor-pointer overflow-hidden"
            data-choice="right">
            <div class="absolute inset-0 bg-gradient-to-br from-blue-500/20 to-purple-500/20 rounded-lg"></div>
            <div id="simple-rightdots" class="absolute inset-0 p-4"></div>
            <div
              class="absolute inset-0 flex items-center justify-center bg-black/10 hover:bg-black/20 transition-colors rounded-lg">
              <!-- <span class="text-white text-2xl font-bold opacity-0 hover:opacity-100 transition-opacity">点击选择</span> -->
            </div>
            <!--                        <div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 text-white font-bold text-lg">右边</div>-->
          </div>
        </div>
      </div>
    </div>

    <!-- 登录界面-->
    <div id="log-in"
      class="max-w-3xl mx-auto bg-white/20 backdrop-blur-lg rounded-2xl shadow-xl p-8 transform transition-all duration-500 border border-white/30">
      <div class="text-center mb-8">
        <div class="relative inline-block">
          <i class="fa-solid fa-user text-white text-7xl mb-4"></i>
          <i
            class="fa-solid fa-magic-wand-sparkles text-primary text-5xl absolute top-6 left-1/2 transform -translate-x-1/2 animate-pulse"></i>
        </div>
        <h2 class="text-[clamp(1.5rem,3vw,2rem)] font-bold text-white mb-3">
          请填写你的魔法学徒信息
        </h2>
        <p class="text-white/80 leading-relaxed max-w-xl mx-auto">
          所有带 <span class="text-red-400">*</span> 的字段为必填项
        </p>
      </div>

      <!--  -->
      <form id="info-form" class="space-y-6 text-white" onsubmit="event.preventDefault(); logInto();">
        <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
          <!-- 年级 -->
          <div class="form-group">
            <label for="grade" class="block text-sm font-medium text-white/70 mb-1">
              年级 <span class="text-red-400">*</span>
            </label>
            <input type="number" id="grade" name="grade"
              class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300"
              required placeholder="请输入阿拉伯数字" />
          </div>

          <!-- 班级 -->
          <div class="form-group">
            <label for="class" class="block text-sm font-medium text-white/70 mb-1">
              班级 <span class="text-red-400">*</span>
            </label>
            <input type="number" id="class" name="class"
              class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300"
              required placeholder="请输入阿拉伯数字" />
          </div>
        </div>

        <!-- 姓名 -->
        <div class="form-group">
          <label for="name" class="block text-sm font-medium text-white/70 mb-1">
            姓名 <span class="text-red-400">*</span>
          </label>
          <input type="text" id="name" name="name"
            class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300"
            required placeholder="请输入你的真实姓名" />
        </div>

        <!-- 学号 -->
        <div class="form-group">
          <label for="student-id" class="block text-sm font-medium text-white/70 mb-1">
            学号 <span class="text-red-400">*</span>
          </label>
          <input type="text" id="student-id" name="student-id"
            class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300"
            required placeholder="请输入阿拉伯数字" />
        </div>

        <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
          <!-- 年龄 -->
          <div class="form-group">
            <label for="age" class="block text-sm font-medium text-white/70 mb-1">
              年龄 <span class="text-red-400">*</span>
            </label>
            <input type="number" id="age" name="age"
              class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300"
              required placeholder="请输入阿拉伯数字" />
          </div>

          <!-- 性别 -->
          <div class="form-group">
            <label for="gender" class="block text-sm font-medium text-white/70 mb-1">
              性别 <span class="text-red-400">*</span>
            </label>
            <select id="gender" name="gender"
              class="w-full bg-white/10 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-primary/50 transition-all duration-300 appearance-none bg-no-repeat bg-right-[15px] bg-center"
              required>
              <option value="" class="text-white/70" selected disabled style="color: #c8c8c8">
                请选择
              </option>
              <option value="男" class="text-gray-950">男</option>
              <option value="女" class="text-gray-950">女</option>
            </select>
          </div>
        </div>

        <div class="text-center mt-8">
          <button id="click-on"
            class="bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
            确认信息 <i class="fa-solid fa-arrow-right ml-2"></i>
          </button>
        </div>
      </form>
    </div>

    <!--正确页面-->
    <div id="right-page"
      class="flex-grow container mx-auto px-4 py-8 relative z-10 flex justify-center items-center hidden transition-opacity">
      <span
        class="text-[clamp(8rem,20vw,16rem)] text-white font-bold drop-shadow-2xl transform transition-transform">&#10004;</span>
    </div>
    <!--  duration-300 hover:scale-110 -->
    <!--错误页面-->
    <div id="wrong-page"
      class="flex-grow container mx-auto px-4 py-8 relative z-10 flex justify-center items-center hidden transition-opacity">
      <span
        class="text-[clamp(8rem,20vw,16rem)] text-white font-bold drop-shadow-2xl transform transition-transform">&#10006;</span>
    </div>

    <!-- 结果页面 -->
    <div id="results-screen"
      class="transition-opacity max-w-3xl mx-auto bg-white/20 backdrop-blur-lg rounded-2xl shadow-xl p-8 hidden transform transition-all duration-500 border border-white/30">
      <div class="text-center mb-8">
        <div class="relative inline-block">
          <i class="fa-solid fa-trophy text-yellow-400 text-7xl mb-4"></i>
          <i class="fa-solid fa-star text-white text-2xl absolute top-4 left-1/4 animate-pulse"></i>
          <i class="fa-solid fa-star text-white text-2xl absolute top-10 right-1/4 animate-pulse"></i>
          <!-- style='animation-delay: 0.5s'  -->
        </div>
        <h2 class="text-[clamp(1.5rem,3vw,2rem)] font-bold text-white mb-3">
          恭喜你完成了挑战！
        </h2>
        <p class="text-white/80">你已经证明了自己是一位真正的气泡魔法师</p>
      </div>

      <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
        <div class="bg-white/10 rounded-xl p-6 border border-white/20">
          <h3 class="font-semibold text-lg text-white mb-4 flex items-center justify-center">
            <i class="fa-solid fa-check-circle text-success mr-2"></i>
            正确关卡
          </h3>
          <div class="text-center">
            <span id="correct-count" class="text-4xl font-bold text-white">0</span>
            <span class="text-white/70 ml-1">/10</span>
          </div>
        </div>

        <div class="bg-white/10 rounded-xl p-6 border border-white/20">
          <h3 class="font-semibold text-lg text-white mb-4 flex items-center justify-center">
            <i class="fa-solid fa-bolt text-warning mr-2"></i> 平均反应速度
          </h3>
          <div class="text-center">
            <span id="avg-reaction-time" class="text-4xl font-bold text-white">0</span>
            <span class="text-white/70 ml-1">秒</span>
          </div>
        </div>

        <div class="bg-white/10 rounded-xl p-6 border border-white/20 col-span-1 md:col-span-2">
          <h3 class="font-semibold text-lg text-white mb-4 flex items-center justify-center">
            <i class="fa-solid fa-chart-line text-primary mr-2"></i>
            反应速度分析
          </h3>
          <div id="reaction-time-chart" class="h-48"></div>
        </div>
      </div>

      <div class="text-center mb-6">
        <button id="download-data-btn"
          class="bg-gradient-to-r from-green-500 to-blue-500 hover:from-green-600 hover:to-blue-600 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
          <i class="fa-solid fa-download mr-2"></i> 下载实验数据
        </button>
      </div>

      <div class="text-center">
        <button id="restart-btn"
          class="bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-semibold py-3 px-8 rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-white/30">
          再次挑战 <i class="fa-solid fa-refresh ml-2"></i>
        </button>
      </div>
    </div>
  </main>

  <!-- 页脚区域 -->
  <footer class="bg-white/10 backdrop-blur-md text-white py-6 relative z-10">
    <div class="container mx-auto px-4 text-center">
      <p class="text-white/70">气泡魔法世界 &copy; 2025</p>
    </div>
  </footer>
</body>
<script>
  // 实验配置
  const config = {
    delayed: 30 * 1000, // 延迟时间 30毫秒
    totalTrials: 10,
    dotMin: 10,
    dotMax: 30,
    timeLimit: 3, // 秒
    bubbleSizeRange: [15, 35], // 气泡大小范围(px)
    bubbleColors: ["bubble1", "bubble2", "bubble3", "bubble4", "bubble5"],
  };

  // 实验状态
  let state = {
    step: -1, //当前测试步骤默认-1
    stepData: {
      leftDot: 4,
      rightDot: 1,
      successive: 0, //连续正确次数
      fail: 0, //错误次数
      complete: 0, //完成次数
      list: [], //生成每个实验数据 {level, leftDot, rightDot,easy?}
      levelData: {}, //每个水平对应的数量
      easyOrNot: {}, //是否为容易水平
    },
    MEL: 0, // 平均反应速度
    gameData: [],
    step4Data: {
      selectType: "",
      selectReactionTime: "",
      happyScore: 0,
      tiredScore: 0,
    },
    dotsCount: { left: 0, right: 0 }, //生成的点数 更准确
    correctSide: "",
    timer: null,
    timeRemaining: config.timeLimit,
    results: [],
    startTime: 0,
    experimentCountData: {
      step_1: 35,
      step_2: 40,
      step_3: 32,
      step_4: 64,
      // step_1: 5,
      // step_2: 5,
      // step_3: 5,
      // step_4: 5,
    },
    timeExpired: false,
    participantId: generateParticipantId(),
  };

  let simpleWelcome,
    start,
    gamePause,
    select_pause,
    gameContinue,
    start_beforeEl,
    step_0_El,
    step_1_El,
    step_2_El,
    step_3_El,
    step_4_El,
    score_1_El,
    score_2_El,
    score_3_EL,
    experiment_scoreEl,
    simpleExperiment,
    resultsScreen,
    step_tipsEl,
    step_2_tipsEl,
    restartBtn,
    logIn,
    clickOn,
    downloadDataBtn,
    simpleLeft,
    simpleRight,
    simpleLeftDots,
    simpleRightDots,
    rightPage,
    wrongPage,
    trialCount,
    timerEl,
    progressBar,
    simpleProgressBar,
    correctCount,
    avgReactionTime,
    reactionTimeChart,
    infoForm;
  let reactionList = [];
  let csvFile = [];

  let stepMap = {},
    scoreMap = {};
  let isEntering = false;

  let timer = null;
  let step_4_timer = null;
  let step_4_timer_count = 10;


  // DOM 元素
  function initDOM() {
    csvFile = [];
    simpleWelcome = document.getElementById("simple-welcome");
    start = document.getElementById("start");
    step_0_El = document.getElementById("step0");
    step_1_El = document.getElementById("step1");
    step_2_El = document.getElementById("step2");
    step_3_El = document.getElementById("step3");
    step_4_El = document.getElementById("step4");
    score_1_El = document.getElementById("score1");
    score_2_El = document.getElementById("score2");
    score_3_EL = document.getElementById("score3");
    score_4_EL = document.getElementById("score4");
    start_beforeEl = document.getElementById("start-before");
    experiment_scoreEl = document.getElementById("experiment-score");
    step_tipsEl = document.getElementById("step_tips");
    step_2_tipsEl = document.getElementById("step_2_tips");
    simpleExperiment = document.getElementById("simple-experiment");
    gamePause = document.getElementById("game-pause");
    select_pause = document.getElementById("select-pause");
    resultsScreen = document.getElementById("results-screen");
    gameContinue = document.getElementById("game-continue");
    restartBtn = document.getElementById("restart-btn");
    logIn = document.getElementById("log-in");
    downloadDataBtn = document.getElementById("download-data-btn");
    simpleLeft = document.getElementById("simple-left");
    simpleRight = document.getElementById("simple-right");
    simpleLeftDots = document.getElementById("simple-leftdots");
    simpleRightDots = document.getElementById("simple-rightdots");
    rightPage = document.getElementById("right-page");
    wrongPage = document.getElementById("wrong-page");
    // trialCount = document.getElementById('trial-count');
    timerEl = document.getElementById("timerEl");
    progressBar = document.getElementById("progress-bar");
    simpleProgressBar = document.getElementById("simple-progress");
    correctCount = document.getElementById("correct-count");
    avgReactionTime = document.getElementById("avg-reaction-time");
    reactionTimeChart = document.getElementById("reaction-time-chart");
    infoForm = document.getElementById("info-form");

    stepMap = { step_0_El, step_1_El, step_2_El, step_3_El, step_4_El };
    scoreMap = { score_1_El, score_2_El, score_3_EL };
  }

  initDOM();

  const container = document.querySelector('.rect-container');
  const rect = document.querySelector('.rect');


  // 为数字输入字段添加实时验证
  const numberInputs = infoForm.querySelectorAll(
    'input[type="number"], #student-id'
  );
  numberInputs.forEach(input => {
    input.addEventListener("input", function () {
      // 只允许输入数字
      this.value = this.value.replace(/[^0-9]/g, "");
    });
  });

  // 首次开始冒险
  function startSimpleExperiment() {
    simpleWelcome.classList.add("opacity-0", "hidden");
    simpleExperiment.classList.remove("hidden", "opacity-0");
    simpleExperiment.classList.add("opacity-100");
    state.step = -1;
    state.stepData.leftDot = 4;
    state.stepData.rightDot = 1;
    simpleGenerateTrial(state.stepData.leftDot, state.stepData.rightDot);
  }

  // 开始实验
  async function startExperiment(step) {
    stepMap[`step_${state.step + 1}_El`].classList.add("opacity-0", "hidden");

    state.step = step;
    state.stepData.fail = 0;
    state.stepData.successive = 0;
    state.stepData.complete = 0;
    state.stepData.list = [];
    state.correctSide = "";
    config.timeLimit = 3;

    // 0和1 开始后直接显示实验选择页面 其他步骤要等待提示结束后才显示
    if (step == 0 || step == -1) {
      simpleExperiment.classList.remove("hidden", "opacity-0");
      simpleExperiment.classList.add("opacity-100");
    }

    if (step == -1) {
      state.stepData.leftDot = 4;
      state.stepData.rightDot = 1;
      state.gameData = [];
    }

    if (step == 0) {
      state.stepData.leftDot = 8;
      state.stepData.rightDot = 5;
      state.gameData = [];
    }

    if (step == 1) {
      // 添加每个水平对应的数量
      for (let i = 1; i <= 4; i++) {
        for (let j = 0; j < 8; j++) {
          let left = Math.floor(state.MEL * (i * 0.2));
          state.stepData.list.push({
            level: i,
            leftDot: left,
            rightDot: left + 3,
          });
        }
      }

      // 添加努力水平 0，3 次
      for (let j = 0; j < 3; j++) {
        state.stepData.list.push({ level: 0, leftDot: 0, rightDot: 0 });
      }
      arrayshuffle(state.stepData.list);
      console.log(state.stepData.list, "打乱后的数组");

      // 开始实验
      await showStep1Tips(getCurrentList());

      simpleGenerateTrial(
        getCurrentList().leftDot,
        getCurrentList().rightDot
      );

      state.gameData = [];
      state.dotsCount = { left: 0, right: 0 };
      return;
    }

    if (step == 2) {
      let gameDataObj = {};
      state.gameData.map(item => {
        if (item.level > 0) {
          if (gameDataObj[item.level]) {
            gameDataObj[item.level].push(item);
          } else {
            gameDataObj[item.level] = [item];
          }
        }
      });
      // 添加每个水平对应的数量
      for (let i = 1; i <= 4; i++) {
        state.stepData.levelData[i] = (gameDataObj[i] || [])
          .reverse()
          .filter(item => item.correct === "是")
          .slice(0, 5)
          .map(item => item.reactionTime);

        state.stepData.easyOrNot[i] = {
          0: getPercentile(state.stepData.levelData[i], 0.2),
          1: getPercentile(state.stepData.levelData[i], 0.8),
        }

        for (let k = 0; k < 2; k++) {
          for (let j = 0; j < 5; j++) {
            let left = Math.floor(state.MEL * (i * 0.2));
            state.stepData.list.push({
              level: i,
              leftDot: left,
              rightDot: left + 3,
              easy: k, //1是容易的,0是不容易的
            });
          }
        }
      }

      arrayshuffle(state.stepData.list);
      console.log(state.stepData.list, "打乱后的数组", "easyOrNot", state.stepData.easyOrNot);

      // 开始实验

      const { list, complete, easyOrNot } = state.stepData;

      await showStep1Tips(list[complete]);

      config.timeLimit = easyOrNot[list[complete].level][list[complete].easy];

      simpleGenerateTrial(list[complete].leftDot, list[complete].rightDot);

      state.gameData = [];
      return;
    }

    if (step == 3) {
      // 添加每个水平对应的数量
      for (let i = 1; i <= 4; i++) {
        for (let k = 0; k < 2; k++) {
          for (let j = 0; j < 4; j++) {
            state.stepData.list.push({
              level: i,
              easy: k, //1是容易的,0是不容易的
            });
          }
        }
      }

      arrayshuffle(state.stepData.list);
      console.log(state.stepData.list, "打乱后的数组");

      // 开始实验

      const { list, complete } = state.stepData;

      await showStep1Tips(list[complete], false);

      state.startTime = performance.now();
      state.gameData = [];
      return;
    }

    if (step == 4) {
      // 添加每个水平对应的数量
      for (let i = 1; i <= 4; i++) {
        for (let k = 0; k < 2; k++) {
          for (let j = 0; j < 8; j++) {
            let left = Math.floor(state.MEL * (i * 0.2));
            state.stepData.list.push({
              level: i,
              easy: k, //1是容易的,0是不容易的
              leftDot: left,
              rightDot: left + 3,
            });
          }
        }
      }

      arrayshuffle(state.stepData.list);
      console.log(state.stepData.list, "打乱后的数组");

      step_4_El.querySelectorAll(".slider-container input").forEach(inputEl => {
        console.log(inputEl.value);
        if (inputEl.title == "开心程度") {
          state.step4Data.happyScore = inputEl.value;
        }
        if (inputEl.title == "疲劳程度") {
          state.step4Data.tiredScore = inputEl.value;
        }
        // 保存提交的值
      })

      experiment_scoreEl.querySelectorAll(".slider-container input").forEach(inputEl => {
        console.log(inputEl.value);
        if (inputEl.title == "开心程度") {
          inputEl.value = state.step4Data.happyScore;
        }
        if (inputEl.title == "疲劳程度") {
          inputEl.value = state.step4Data.tiredScore;
        }
        // 保存提交的值
      })
      getSliderList();

      experiment_scoreEl

      // 开始实验
      const { list, complete, easyOrNot } = state.stepData;

      if (state.step4Data.selectType == 1) {
        config.timeLimit = easyOrNot[list[complete].level][list[complete].easy];
      }
      waitFun()
      await showStep1Tips(list[complete], false);


      state.gameData = [];
      return;
    }

    simpleGenerateTrial(state.stepData.leftDot, state.stepData.rightDot);
  }

  async function step4Score() {
    experiment_scoreEl.querySelectorAll(".slider-container input").forEach(inputEl => {
      console.log(inputEl.value);
      if (inputEl.title == "开心程度") {
        state.gameData[state.stepData.complete - 1].happyScore = inputEl.value;
      }
      if (inputEl.title == "疲劳程度") {
        state.gameData[state.stepData.complete - 1].tiredScore = inputEl.value;
      }
      // 保存提交的值
    })
    experiment_scoreEl.classList.add("hidden", "opacity-0");


    if (state.stepData.complete >= state.experimentCountData.step_4) {
      step4End()
      return
    }

    const { list, complete, easyOrNot } = state.stepData;

    waitFun()
    await showStep1Tips(list[complete], false);


    // config.timeLimit = easyOrNot[list[complete].level][list[complete].easy];
    // simpleGenerateTrial(list[complete].leftDot, list[complete].rightDot);
  }

  async function step4End() {
    downloadExperimentData();
    simpleExperiment.classList.add("hidden", "opacity-0"); // 
    // 遍历所有 CSV 内容，转成 Blob 并添加到 zip
    const zip = new JSZip();
    for (const file of csvFile) {
      const blob = new Blob([file.content], { type: "text/csv;charset=utf-8;" });
      zip.file(file.name, blob);
    }
    // 生成 ZIP 并触发下载
    const zipBlob = await zip.generateAsync({ type: 'blob' });
    let infoData = getInfoForm();

    let fileName = `${infoData.formData.get('grade')}_${infoData.formData.get('class')}_${infoData.formData.get('name')}_${infoData.formData.get('student-id')}_.zip`

    downloadFun(zipBlob, fileName);
    alert("实验结束");
  }

  function waitFun() {
    // 倒计时
    step_4_timer_count = 10;

    if (step_4_timer) {
      clearInterval(step_4_timer);
    }

    step_4_timer = setInterval(async () => {
      if (step_4_timer_count > 0) {
        step_4_timer_count--;
      } else {
        let currentData = {
          correct: "否",
          reactionTime: 10,
          timeout: "是",
          feedback: "",
          standardTime: getCurrentList().standardTime,
          leftDot: state.dotsCount.left,
          rightDot: state.dotsCount.right,
          happyScore: 0,
          tiredScore: 0,
          select: "超时",
          selectReactionTime: 10,
          easy: state.stepData.list.length && getCurrentList()?.easy,
          level:
            state.stepData.list.length && getCurrentList()?.level,
        };

        state.gameData.push(currentData);
        if (state.stepData.complete >= state.experimentCountData.step_4) {
          step4End()
          clearInterval(step_4_timer);
          return;
        }
        state.stepData.complete++;
        const { list, complete } = state.stepData;
        clearInterval(step_4_timer);
        await showStep1Tips(list[complete], false);
        state.startTime = performance.now();
        waitFun()
      }
      console.log(step_4_timer_count);
    }, 1000);
  }

  // 选择实验模式
  async function selectFun(type) {
    const { list, complete, easyOrNot } = state.stepData;
    const endTime = performance.now();
    const selectReactionTime = ((endTime - state.startTime) / 1000).toFixed(2);
    if (state.step == 3) {
      state.stepData.complete++;

      state.gameData.push({
        level: list[complete].level,
        easy: list[complete].easy,
        select: type == 1 ? "付出努力" : "休息",
        selectReactionTime,
      });

      if (state.stepData.complete >= state.experimentCountData.step_3) {
        step_2_tipsEl.classList.add("hidden", "opacity-0");
        // 
        downloadExperimentData();

        realExperiment();
        return;
      }
      step_2_tipsEl.classList.add("hidden", "opacity-0");
      step_2_tipsEl.classList.remove("opacity-100");

      // 延迟1.5秒
      select_pause.classList.remove("hidden", "opacity-0");
      select_pause.innerText = "你选择了" + (type == 1 ? "释放魔法" : "休息");
      await new Promise(resolve => setTimeout(resolve, 1500));
      select_pause.classList.add("hidden", "opacity-0");

      await showStep1Tips(list[state.stepData.complete], false);
      state.startTime = performance.now();
    } else if (state.step == 4) {
      clearInterval(step_4_timer);
      // 
      step_2_tipsEl.classList.add("hidden", "opacity-0");
      simpleExperiment.classList.remove("opacity-0", "hidden");
      simpleExperiment.classList.add("opacity-100");

      state.step4Data.selectType = type;
      state.step4Data.selectReactionTime = selectReactionTime;
      config.timeLimit = 3;
      if (type == 1) {
        config.timeLimit = getCurrentList().standardTime;
        simpleGenerateTrial(list[complete].leftDot, list[complete].rightDot);
      } else {
        simpleGenerateTrial(0, 0);
      }
    }
  }

  function gameContinueFun() {
    gamePause.classList.add("hidden", "opacity-0");
    simpleExperiment.classList.remove("hidden", "opacity-0");
    simpleGenerateTrial(state.stepData.leftDot, state.stepData.rightDot);
  }

  //登录
  function logInto() {
    // 验证表单
    if (!infoForm.checkValidity()) {
      infoForm.reportValidity();
      return;
    }

    // 添加用户数据
    let infoData = getInfoForm()
    let csvContent = infoData.headers.join(",") + "\n";
    csvContent += infoData.headerContent.join(",") + "\n";
    // 创建并下载CSV文件
    csvFile.push({ name: "魔法学徒信息.csv", content: csvContent });
    // const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
    // downloadFun(blob, "魔法学徒信息")

    logIn.classList.add("opacity-0");
    setTimeout(() => {
      logIn.classList.add("hidden");
      simpleWelcome.classList.remove("hidden", "opacity-0");
      simpleWelcome.classList.add("opacity-100");
    }, 500);
    start.classList.add("disabled-button"); // 初始时添加禁用样式

    setTimeout(() => {
      start.removeAttribute("disabled"); // 移除 disabled 属性，使按钮可点击
      start.classList.remove("disabled-button"); // 移除禁用样式
    }, config.delayed); // 30 秒后启用按钮
  }

  // 处理不同的step
  async function handleStepClick(isCorrect, currentData) {
    // 判断不同的步骤
    // 进入下一试次或显示结果
    if (state.step == -1) {
      if (isCorrect) {
        if (currentData.timeout == "否") {
          state.stepData.successive++;
          simpleExperiment.classList.remove("hidden", "opacity-0"); // 显示 simpleExperiment
        } else {
          state.stepData.successive = 0;
          simpleWelcome.classList.remove("hidden", "opacity-0"); // 显示 simpleExperiment
          simpleWelcome.classList.add("opacity-100"); // 显示 simpleExperiment
          simpleExperiment.classList.add("hidden", "opacity-0"); // 显示 simpleExperiment
          return;
        }
      } else {
        state.stepData.successive = 0;
        simpleWelcome.classList.remove("hidden", "opacity-0"); // 显示 simpleExperiment
        simpleWelcome.classList.add("opacity-100"); // 显示 simpleExperiment
        simpleExperiment.classList.add("hidden", "opacity-0"); // 显示 simpleExperiment
        return;
      }

      if (state.stepData.successive < 5) {
        simpleGenerateTrial();
      } else if (state.stepData.successive >= 5) {
        // 进入下一步骤
        state.stepData.successive = 0;
        realExperiment();
      }
    }

    if (state.step == 0) {
      state.stepData.complete++;
      simpleExperiment.classList.remove("hidden", "opacity-0"); // 显示 simpleExperiment
      //

      // realExperiment();
      // return;
      if (isCorrect) {
        state.stepData.successive++;
        // state.stepData.fail = 0;
        console.log(
          "连续成功次数:",
          state.stepData.successive,
          "失败次数:",
          state.stepData.fail
        );
        if (state.stepData.successive >= 4) {
          state.stepData.leftDot += 2;
          state.stepData.rightDot += 2;
          state.stepData.successive = 0;

          let min = Math.min(state.stepData.leftDot, state.stepData.rightDot);
          state.MEL = min;
          if (state.stepData.fail >= 2 && min > 5) {
            // 结束实验
            downloadExperimentData();
            if (min <= 5) {
              // 实验结束
              console.log("实验结束");
            } else {
              //
              console.log("继续实验");
              // 继续实验
              realExperiment();
            }
            return;
          }
        }
      } else {
        state.stepData.fail++;
        state.stepData.leftDot -= 1;
        state.stepData.rightDot -= 1;
        state.stepData.successive = 0;
      }

      if (state.stepData.complete >= 10) {
        // 休息
        gamePause.classList.remove("hidden", "opacity-0");
        gameContinue.classList.add("disabled-button"); // 初始时添加禁用样式
        simpleExperiment.classList.add("hidden", "opacity-0"); // 显示 simpleExperiment

        setTimeout(() => {
          gameContinue.removeAttribute("disabled"); // 移除 disabled 属性，使按钮可点击
          gameContinue.classList.remove("disabled-button"); // 移除禁用样式
          state.stepData.complete = 0;
        }, 10 * 1000); // 10 秒后启用按钮
        return;
      }
      console.log(state, state.stepData.successive);
      simpleGenerateTrial(state.stepData.leftDot, state.stepData.rightDot);
    }

    if (state.step == 1) {
      state.stepData.complete++;

      if (isCorrect) {
        state.stepData.successive++;
        console.log("连续成功次数:", state.stepData.successive);
      } else {
        state.stepData.successive = 0;
      }
      if (state.stepData.complete >= state.experimentCountData.step_1) {
        downloadExperimentData();
        stepMap[`step_${state.step + 1}_El`].classList.add(
          "hidden",
          "opacity-0"
        );
        score_1_El.classList.remove("hidden");
        getSliderList();
        return;
      }
      const { list, complete } = state.stepData;
      console.log(state, state.stepData.successive, list, complete);

      await showStep1Tips(list[complete]);

      simpleGenerateTrial(list[complete].leftDot, list[complete].rightDot);
    }

    if (state.step == 2) {
      state.stepData.complete++;

      if (isCorrect) {
        state.stepData.successive++;
        // 动态更新反应时间
        updateReactionTimeAndPercentile(currentData);
      } else {
        state.stepData.successive = 0;
      }

      if (state.stepData.complete >= state.experimentCountData.step_2) {
        downloadExperimentData();
        stepMap[`step_${state.step + 1}_El`].classList.add(
          "hidden",
          "opacity-0"
        );
        score_2_El.classList.remove("hidden");
        getSliderList();
        return;
      }

      const { list, complete, levelData, easyOrNot } = state.stepData;
      console.log(
        state,
        state.stepData.successive,
        list,
        complete,
        levelData,
        "更新后的分位数",
        easyOrNot[currentData.level]
      );
      await showStep1Tips(list[complete]);

      config.timeLimit = easyOrNot[currentData.level][list[complete].easy];

      simpleGenerateTrial(list[complete].leftDot, list[complete].rightDot);
    }

    if (state.step == 4) {
      state.stepData.complete++;

      if (isCorrect) {
        state.stepData.successive++;
        // 动态更新反应时间
        updateReactionTimeAndPercentile(currentData);
      } else {
        state.stepData.successive = 0;
      }
      const { list, complete, levelData, easyOrNot } = state.stepData;
      console.log(
        state,
        list,
        complete,
        levelData,
        "更新后的分位数",
        easyOrNot[currentData.level]
      );
      // await 评分后
      // 显示打分页面
      experiment_scoreEl.classList.remove("hidden", "opacity-0");
      experiment_scoreEl.classList.add("opacity-100");
      getSliderList()
    }
  }

  function getCurrentList() {
    let data = state.stepData.list[state.stepData.complete];
    console.trace(data);
    if (!data) return "";
    return {
      ...data,
      standardTime: (data.level && data.easy != undefined || data.easy != null) ? state.stepData.easyOrNot?.[data?.level]?.[data?.easy] : 0,
    }
  }

  // 重新开始实验
  function restartExperiment() {
    state = {
      step: -1, //当前测试步骤默认
      stepData: {
        successive: 0, //连续正确次数
        fail: 0, //错误次数
        complete: 0, //完成次数
      },
      dotsCount: { left: 0, right: 0 },
      correctSide: "",
      timer: null,
      timeRemaining: config.timeLimit,
      results: [],
      startTime: 0,
      timeExpired: false,
      participantId: generateParticipantId(),
    };
    resultsScreen.classList.add("opacity-0");
    setTimeout(() => {
      resultsScreen.classList.add("hidden");
      simpleExperiment.classList.remove("hidden", "opacity-0");
      progressBar.style.width = "10%";
      // trialCount.textContent = '1';
      simpleGenerateTrial();
    }, 500);
  }

  // 实验显示区域点击事件
  async function simpleClick(selectedSide) {
    // 休息时禁止点击
    if (state.step == 1 && getCurrentList().level == 0) {
      return;
    }
    if (state.step == 4 && state.step4Data.selectType == 0) {
      return;
    }

    const selectedElement =
      selectedSide === "left" ? simpleLeft : simpleRight;
    // 如果已经选择过了，不做处理
    if (
      selectedElement.classList.contains("border-success") ||
      selectedElement.classList.contains("border-warning") ||
      selectedElement.classList.contains("border-error")
    ) {
      return;
    }
    clearInterval(state.timer);
    // 计算反应时间
    const endTime = performance.now();
    const reactionTime = (endTime - state.startTime) / 1000;
    // 判断是否正确
    const isCorrect = selectedSide === state.correctSide;
    const isWithinTime = reactionTime <= config.timeLimit;

    let currentData = {
      correct: isCorrect ? "是" : "否",
      reactionTime: reactionTime.toFixed(2),
      timeout: isWithinTime ? "否" : "是",
      feedback: "",
      standardTime: getCurrentList().standardTime,
      leftDot: state.dotsCount.left,
      rightDot: state.dotsCount.right,
      happyScore: 0,
      tiredScore: 0,
      easy: state.stepData.list.length && getCurrentList()?.easy,
      level:
        state.stepData.list.length && getCurrentList()?.level,
    };
    if (state.step == 4) {
      currentData.select = state.step4Data.selectType == 1 ? "付出努力" : "休息";
      currentData.selectReactionTime = state.step4Data.selectReactionTime;
    }
    // 显示点击反馈
    // 让气泡"弹出"效果
    const bubbles = selectedElement.querySelectorAll(".bubble");
    bubbles.forEach(bubble => {
      bubble.classList.add("bubble-pop");
    });

    // 正确选择
    if (isCorrect) {
      selectedElement.classList.add("feedback-animation");
      if (isWithinTime) {
        // 快速正确
        selectedElement.classList.add("border-success");
        currentData.feedback = "绿色";
      } else {
        // 慢速正确
        selectedElement.classList.add("border-warning");
        currentData.feedback = "黄色";
      }
    } else {
      // 错误选择
      selectedElement.classList.add("border-error", "feedback-animation");
      currentData.feedback = "红色";
      // 同时显示正确答案
      const correctElement =
        state.correctSide === "left" ? simpleLeft : simpleRight;
      correctElement.classList.add("border-success");
    }

    // 保存游戏数据
    state.gameData.push(currentData);

    // 隐藏选项气泡 后显示正确或错误符号
    await new Promise(resolve => {
      setTimeout(() => {
        simpleExperiment.classList.add("opacity-0", "hidden");
        if (isCorrect && isWithinTime) {
          rightPage.classList.remove("hidden", "opacity-0");
          rightPage.classList.add("opacity-100");
        } else {
          wrongPage.classList.remove("hidden", "opacity-0");
          wrongPage.classList.add("opacity-100");
        }
        resolve();
      }, 500);
    });

    // 隐藏正确或错误符号
    await new Promise(resolve => {
      setTimeout(() => {
        if (isCorrect && isWithinTime) {
          rightPage.classList.remove("opacity-100"); // 使 rightPage 变为透明
          rightPage.classList.add("hidden", "opacity-0");
        } else {
          wrongPage.classList.remove("opacity-100"); // 使 rightPage 变为透明
          wrongPage.classList.add("hidden", "opacity-0");
        }
        resolve();
      }, 1500);
    });

    handleStepClick(isCorrect, currentData);
  }

  // 继续下一步
  function realExperiment() {
    simpleExperiment.classList.add("opacity-0", "hidden");

    stepMap[`step_${state.step + 1}_El`].classList.remove(
      "hidden",
      "opacity-0"
    );

    stepMap[`step_${state.step + 1}_El`].classList.add("opacity-100");
    getSliderList();

    let startBtn =
      stepMap[`step_${state.step + 1}_El`].querySelector(".start-btn");

    startBtn.classList.add("disabled-button"); // 初始时添加禁用样式

    setTimeout(() => {
      startBtn.removeAttribute("disabled"); // 移除 disabled 属性，使按钮可点击
      startBtn.classList.remove("disabled-button"); // 移除禁用样式
    }, state.step == -1 ? 10 * 1000 : config.delayed); // 30 秒后启用按钮
  }

  // 随机打乱数组
  function arrayshuffle(array) {
    // 打乱数组（Fisher–Yates shuffle）
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
  }

  function updateLabel(slider, label) {
    const value = parseInt(slider.value);
    label.textContent = value;

    const min = parseInt(slider.min);
    const max = parseInt(slider.max);
    const percent = (value - min) / (max - min);

    const sliderWidth = slider.offsetWidth - 15;
    const labelLeft = percent * sliderWidth;

    label.style.left = `${labelLeft}px`;
  }

  // 遍历所有 slider-container
  function getSliderList() {
    document.querySelectorAll(".slider-container").forEach(container => {
      const slider = container.querySelector(".slider");
      const label = container.querySelector(".value-label");
      slider.addEventListener("input", () => updateLabel(slider, label));
      updateLabel(slider, label); // 初始化
    });
  }
  getSliderList()

  // --------------------------------&公共方法区&---------------------------------------//

  function showStep1Tips(data, showSimpleExperiment = true) {
    simpleExperiment.classList.add("hidden", "opacity-0");
    return new Promise(resolve => {
      let imgMap = new Map([
        [0, "./img/effort.png"],
        [1, "./img/effort1.png"],
        [2, "./img/effort2.png"],
        [3, "./img/effort3.png"],
        [4, "./img/effort4.png"],
      ]);

      let tipsEl = (state.step == 1 || state.step == 2) ? step_tipsEl : step_2_tipsEl;


      tipsEl.querySelector(".level-title").innerHTML = data.level
        ? "努力水平" + data.level
        : "休息";
      tipsEl.querySelector(".level-img").src = imgMap.get(data.level);

      tipsEl.querySelector(".easy").classList.add("hidden");

      if (state.step != 1) {
        tipsEl.querySelector(".easy").classList.remove("hidden");
        tipsEl.querySelector(".easy-title").innerHTML =
          data.easy == 1 ? "容易成功" : "不容易成功";
        tipsEl.querySelector(".easy-img").src =
          data.easy == 1 ? "./img/easy.png" : "./img/not-easy.png";
      }


      tipsEl.classList.remove("hidden", "opacity-0");
      tipsEl.classList.add("opacity-100");

      setTimeout(() => {
        if (showSimpleExperiment) {
          tipsEl.classList.add("hidden", "opacity-0");
          simpleExperiment.classList.remove("opacity-0", "hidden");
          simpleExperiment.classList.add("opacity-100");
        }
        if (state.step == 4) {
          state.startTime = performance.now();
        }
        resolve();
      }, 1500);
    });
  }

  // 下载实验数据
  function downloadFun(blob, fileName) {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    a.click();
    URL.revokeObjectURL(url); // 清理资源
  }

  // 生成参与者ID
  function generateParticipantId() {
    return (
      "PARTICIPANT_" +
      Date.now().toString(36).toUpperCase() +
      Math.random().toString(36).substr(2, 5)
    );
  }

  // 生成气泡
  function generateBubbles(container, count) {
    const containerRect = container.getBoundingClientRect();
    const width = containerRect.width;
    const height = containerRect.height;

    // 创建气泡并随机分布
    for (let i = 0; i < count; i++) {
      const bubble = document.createElement("div");

      // 随机大小
      const size = getRandomInt(
        config.bubbleSizeRange[0],
        config.bubbleSizeRange[1]
      );
      bubble.style.width = `${size}px`;
      bubble.style.height = `${size}px`;

      // 随机位置（避免超出容器）
      const x = getRandomInt(0, width - size);
      const y = getRandomInt(0, height - size);
      bubble.style.left = `${x}px`;
      bubble.style.top = `${y}px`;

      // 随机颜色
      const colorIndex = getRandomInt(0, config.bubbleColors.length - 1);
      const color = config.bubbleColors[colorIndex];
      bubble.className = `bubble bg-${color}/80 border border-${color}/70`;

      // 随机不透明度
      const opacity = Math.random() * 0.3 + 0.6;
      bubble.style.opacity = opacity;

      // 随机动画延迟
      const delay = Math.random() * 3;
      bubble.style.animationDelay = `${delay}s`;

      container.appendChild(bubble);
    }
  }

  // 生成随机整数
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  function getInfoForm() {
    const formData = new FormData(infoForm);
    const headers = ["年级", "班级", "姓名", "学号", "年龄", "性别"];
    const headerContent = [
      formData.get("grade"),
      formData.get("class"),
      formData.get("name"),
      formData.get("student-id"),
      formData.get("age"),
      formData.get("gender"),
    ];
    return {
      headers,
      headerContent,
      formData,
    };
  }

  //简单生成试次
  function simpleGenerateTrial(leftDot = 4, rightDot = 1) {

    simpleExperiment.classList.add("opacity-0", "hidden");
    start_beforeEl.classList.remove("hidden", "opacity-0");
    start_beforeEl.classList.add("opacity-100");

    // 休息 不显示蓄力
    if (leftDot == 0 && rightDot == 0) {
      showSimpleExperiment(leftDot, rightDot);
      return
    }

    // 先移除已有事件监听器（防止多次绑定）
    container.removeEventListener('mouseenter', handleMouseEnter);

    function handleMouseEnter() {
      console.log('鼠标移入', timer);
      rect.style.transform = 'translate(-50%, -50%) scale(10)';
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        console.log('鼠标移入事件');
        showSimpleExperiment(leftDot, rightDot);
      }, 1000);
    }

    // 再绑定新的监听器
    container.addEventListener('mouseenter', handleMouseEnter);

    container.addEventListener('mouseleave', () => {
      rect.style.transform = 'translate(-50%, -50%) scale(0)'; // 鼠标移出收回
      isEntering = false;
      clearTimeout(timer);
    });

  }


  function showSimpleExperiment(leftDot, rightDot) {
    console.log(leftDot, rightDot, "----------------------")
    start_beforeEl.classList.add("hidden", "opacity-0");
    start_beforeEl.classList.remove("opacity-100");
    simpleExperiment.classList.remove("hidden", "opacity-0");
    simpleExperiment.classList.add("opacity-100");

    // 重置UI
    resetUI();

    // 计算左右两侧的气泡数量
    leftDotsCount = leftDot;
    rightDotsCount = rightDot;

    // 随机决定哪一侧更多
    if (Math.random() < 0.5) {
      [leftDotsCount, rightDotsCount] = [rightDotsCount, leftDotsCount];
    }
    state.dotsCount.left = leftDotsCount;
    state.dotsCount.right = rightDotsCount;

    // 确定正确的一侧
    state.correctSide = leftDotsCount > rightDotsCount ? "left" : "right";

    // 生成气泡
    generateBubbles(simpleLeftDots, leftDotsCount);
    generateBubbles(simpleRightDots, rightDotsCount);

    // 更新UI
    // trialCount.textContent = state.stepData.successive;
    // simpleProgressBar.style.width = `${(state.stepData.successive / 5) * 100}%`;

    // 开始计时
    startTimer();

    // 记录开始时间
    state.startTime = performance.now();
    state.timeExpired = false;
    // simpleExperiment.classList.remove("opacity-0", "hidden")
  }

  //提交评分
  function submitScore(step) {

    let titleList = [], valueList = [];
    scoreMap[`score_${step}_El`].querySelectorAll(".slider-container input").forEach(inputEl => {
      titleList.push(inputEl.title)
      valueList.push(inputEl.value)
    })
    let infoData = getInfoForm();
    let csvContent = [...infoData.headers, ...titleList].join(",") + "\n";
    csvContent += [...infoData.headerContent, ...valueList].join(",") + "\n";
    // 创建并下载CSV文件
    // const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
    let name = step == 1 ? "effort_slider_results" : "success_slider_results"
    // downloadFun(blob,);
    let fileName = `${infoData.formData.get("name")}_${infoData.formData.get("student-id")}_${name}.csv`

    csvFile.push({ name: fileName, content: csvContent })

    scoreMap[`score_${step}_El`].classList.add("hidden", "opacity-0");
    realExperiment();


  }

  // 重置UI
  function resetUI() {
    simpleLeftDots.innerHTML = "";
    simpleRightDots.innerHTML = "";
    simpleLeft.classList.remove(
      "border-success",
      "border-warning",
      "border-error",
      "feedback-animation",
      "timer-warning"
    );
    simpleRight.classList.remove(
      "border-success",
      "border-warning",
      "border-error",
      "feedback-animation",
      "timer-warning"
    );
    timerEl.classList.remove("text-error", "timer-warning");
  }

  // 开始计时
  function startTimer() {
    state.timeRemaining = config.timeLimit;
    timerEl.textContent = state.timeRemaining;

    // 清除之前的计时器
    if (state.timer) clearInterval(state.timer);

    // 设置新计时器
    state.timer = setInterval(async () => {
      state.timeRemaining--;
      timerEl.textContent = state.timeRemaining;

      // 时间快到了
      if (state.timeRemaining <= 1) {
        timerEl.classList.add("text-error", "timer-warning");
      }

      // 时间到
      if (
        state.timeRemaining <= 0 &&
        !simpleExperiment.classList.contains("hidden")
      ) {
        clearInterval(state.timer);
        state.timeExpired = true;
        timerEl.classList.remove("timer-warning");
        timerEl.textContent = "超时";

        const { list, complete } = state.stepData;


        // 处理休息 自动进入下一步

        if (state.step == 1 && list[complete].level == 0) {
          let currentData = {
            correct: "是",
            reactionTime: 0,
            timeout: "否",
            feedback: "绿色",
            leftDot: state.dotsCount.left,
            rightDot: state.dotsCount.right,
            level: state.stepData.list.length && getCurrentList()?.level,
          };

          state.gameData.push(currentData);

          state.stepData.complete++;
          console.log(state.stepData.list, state.stepData.complete)
          await showStep1Tips(getCurrentList());
          simpleGenerateTrial(
            getCurrentList().leftDot,
            getCurrentList().rightDot
          );
        }

        if (state.step == 4 && state.step4Data.selectType == 0) {

          let currentData = {
            correct: "是",
            reactionTime: 0,
            timeout: "否",
            feedback: "绿色",
            standardTime: 3,
            leftDot: state.dotsCount.left,
            selectReactionTime: state.step4Data.selectReactionTime,
            select: "休息",
            rightDot: state.dotsCount.right,
            easy: state.stepData.list.length && getCurrentList()?.easy,
            level: state.stepData.list.length && getCurrentList()?.level,
          };
          state.gameData.push(currentData);
          state.stepData.complete++;
          simpleExperiment.classList.remove("opacity-100");
          simpleExperiment.classList.add("opacity-0", "hidden");
          experiment_scoreEl.classList.remove("hidden", "opacity-0");
          experiment_scoreEl.classList.add("opacity-100");
        }

      }
    }, 1000);
  }

  // 下载实验数据
  function downloadExperimentData() {
    let infoData = getInfoForm();
    let csvContent;
    // 处理key
    if (state.step == 0) {
      csvContent = [
        ...infoData.headers,
        "左侧气泡数量",
        "右侧气泡数量",
        "是否选择正确的一边",
        "反应时",
        "是否超时",
        "反馈",
      ].join(",") + "\n"
    } else if (state.step == 1) {
      csvContent = [...infoData.headers, "努力水平", "左侧气泡数量",
        "右侧气泡数量",
        "是否选择正确的一边",
        "反应时",
        "是否超时",
        "反馈"].join(",") + "\n"
    } else if (state.step == 2) {
      csvContent = [...infoData.headers, "努力水平", "成功概率水平", "左侧气泡数量",
        "右侧气泡数量",
        "是否选择正确的一边",
        "反应时标准",
        "反应时",
        "是否超时",
        "反馈"].join(",") + "\n"
    } else if (state.step == 3) {
      csvContent = [...infoData.headers, "努力水平", "成功概率水平", "选择休息还是付出努力", "反应时"].join(",") + "\n"

    } else if (state.step == 4) {
      csvContent = [...infoData.headers, "努力水平", "成功概率水平", "选择休息还是付出努力", "做选择反应时", "左侧气泡数量", "右侧气泡数量",
        "是否选择正确的一边",
        "反应时标准",
        "反应时",
        "是否超时",
        "反馈",
        "开心打分",
        "疲劳打分"
      ].join(",") + "\n"
    }

    //处理值
    if (state.step == 0) {
      state.gameData.map(item => {
        csvContent +=
          [
            ...infoData.headerContent,
            item.leftDot,
            item.rightDot,
            item.correct,
            item.reactionTime,
            item.timeout,
            item.feedback,
          ].join(",") + "\n";
      });

    } else if (state.step == 1) {
      state.gameData.map(item => {
        csvContent +=
          [
            ...infoData.headerContent,
            "努力水平" + item.level,
            item.leftDot,
            item.rightDot,
            item.correct,
            item.reactionTime,
            item.timeout,
            item.feedback,
          ].join(",") + "\n";
      });
    } else if (state.step == 2) {
      state.gameData.map(item => {
        csvContent +=
          [
            ...infoData.headerContent,
            "努力水平" + item.level,
            item.easy == 0 ? "不容易成功" : "容易成功",
            item.leftDot,
            item.rightDot,
            item.correct,
            item.standardTime,
            item.reactionTime,
            item.timeout,
            item.feedback,
          ].join(",") + "\n";
      });
    } else if (state.step == 3) {
      state.gameData.map(item => {
        csvContent +=
          [
            ...infoData.headerContent,
            "努力水平" + item.level,
            item.easy == 0 ? "不容易成功" : "容易成功",
            item.select,
            item.selectReactionTime,
          ].join(",") + "\n";
      });
    } else if (state.step == 4) {
      csvContent += [...infoData.headerContent, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, state.step4Data.happyScore, state.step4Data.tiredScore].join(",") + "\n";
      state.gameData.map(item => {
        csvContent +=
          [
            ...infoData.headerContent,
            "努力水平" + item.level,
            item.easy == 0 ? "不容易成功" : "容易成功",
            item.select,
            item.selectReactionTime,
            item.leftDot,
            item.rightDot,
            item.correct,
            item.standardTime,
            item.reactionTime,
            item.timeout,
            item.feedback,
            item.happyScore,
            item.tiredScore,
          ].join(",") + "\n";
      });
    }


    let nameMap = new Map([
      [0, "_MEL_results"],
      [1, "_calibration1_results"],
      [2, "_calibration2_results"],
      [3, "_non_dynamic_results"],
      [4, "_dynamic_results"],
    ]);


    let name = `${infoData.formData.get("name")}_${infoData.formData.get("student-id")}${nameMap.get(state.step)}.csv`

    // 创建并下载CSV文件
    // const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
    // downloadFun(blob,);

    csvFile.push({ name, content: csvContent })
  }

  // 更新反应时和分位数
  function updateReactionTimeAndPercentile(currentData) {
    const { list, complete, levelData, easyOrNot } = state.stepData;

    levelData[currentData.level].shift();
    levelData[currentData.level].push(currentData.reactionTime);

    easyOrNot[currentData.level] = {
      0: getPercentile(levelData[currentData.level], 0.2),
      1: getPercentile(levelData[currentData.level], 0.8),
    };

  }

  /**
   * 计算百分位数
   * @param {Array} arr 数组
   * @param {Number} percentile 百分位数 0.2 0.8
   * @returns {Number} 百分位数值
   */
  function getPercentile(arr, percentile) {
    if (!arr.length) return null;

    // 升序排序副本
    const sorted = [...arr].sort((a, b) => a - b);
    const n = sorted.length;

    const index = (n - 1) * percentile;
    const lower = Math.floor(index);
    const upper = Math.ceil(index);

    if (lower === upper) {
      return sorted[lower]; // 恰好在某个点上
    }

    // 插值
    const weight = index - lower;
    return sorted[lower] * (1 - weight) + sorted[upper] * weight;
  }

  // ----------------------------------end-------------------------------------------//
</script>

</html>